package file

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/nfnt/resize"
	"image"
	"image/jpeg"
	"image/png"
	"io"
	"log"
	"os"
	"path/filepath"
	"strings"
)

func ReceiveFileAndSave(c *gin.Context, saveFullPath string, resizeToSave bool) error {
	// 1. 接收上传的文件
	file, header, err := c.Request.FormFile("file")
	if err != nil {
		return fmt.Errorf("文件获取失败：%v", err)
	}
	defer func() {
		_ = file.Close()
	}()
	//确保目录存在
	dir := filepath.Dir(saveFullPath)
	if err = os.MkdirAll(dir, 0755); err != nil {
		return fmt.Errorf("无法创建目录: %v", err)
	}

	if resizeToSave {
		// 2. 创建临时文件
		tempFileName := "temp_" + header.Filename
		tempFile, err := os.Create(tempFileName)
		if err != nil {
			return fmt.Errorf("临时文件创建失败：%v", err)
		}

		// 确保临时文件最终会被关闭和删除
		defer func() {
			_ = tempFile.Close()
			_ = os.Remove(tempFileName)
		}()

		// 3. 将上传的文件内容拷贝到临时文件
		_, err = io.Copy(tempFile, file)
		if err != nil {
			return fmt.Errorf("文件保存失败：%v", err)
		}

		// 4. 打开临时文件进行图像处理
		_, err = tempFile.Seek(0, 0)
		if err != nil {
			return fmt.Errorf("打开临时文件失败：%v", err)
		}
		img, format, err := image.Decode(tempFile)
		if err != nil {
			return fmt.Errorf("不支持的图像格式：%v", err)
		}

		// 5. 裁剪图像为正方形（按短边）
		img = cropToSquare(img)

		// 6. 如果图像大于150x150，则缩放
		if img.Bounds().Dx() > 150 || img.Bounds().Dy() > 150 {
			img = resize.Resize(150, 150, img, resize.Lanczos3)
		}
		// 7. 生成最终文件名并保存
		outFile, err := os.Create(saveFullPath)
		if err != nil {
			return fmt.Errorf("输出文件创建失败：%v", err)
		}
		defer func() {
			_ = outFile.Close()
		}()

		// 根据格式保存图像
		switch strings.ToLower(format) {
		case "jpeg", "jpg":
			err = jpeg.Encode(outFile, img, nil)
		case "png":
			err = png.Encode(outFile, img)
		default:
			err = fmt.Errorf("不支持的图像格式: %s", format)
		}
		if err != nil {
			_ = os.Remove(saveFullPath) // 删除已创建的空文件
			return fmt.Errorf("图像保存失败：%v", err)
		}
	} else {
		dst, err := os.Create(saveFullPath)
		if err != nil {
			return fmt.Errorf("创建目标文件失败：%v", err)
		}
		defer func() {
			_ = dst.Close()
		}()
		if _, err = io.Copy(dst, file); err != nil {
			_ = os.Remove(saveFullPath) // 删除已创建的空文件
			return fmt.Errorf("文件保存失败：%v", err)
		}
	}
	return nil
}

func IsExists(path string) bool {
	_, err := os.Stat(path)
	if err == nil {
		return true
	}
	if os.IsNotExist(err) {
		return false
	}
	return false
}

func Copy(src, dst string) error {
	// 打开源文件
	srcFile, err := os.Open(src)
	if err != nil {
		return err
	}
	defer func(srcFile *os.File) {
		_ = srcFile.Close()
	}(srcFile)

	// 确保目标目录存在（递归创建）
	dstDir := filepath.Dir(dst)
	if err := os.MkdirAll(dstDir, 0755); err != nil {
		return err
	}

	// 创建目标文件
	dstFile, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer func(dstFile *os.File) {
		_ = dstFile.Close()
	}(dstFile)

	// 拷贝数据
	_, err = io.Copy(dstFile, srcFile)
	return err
}

// 无需判断是否存在
func DeleteFile(filePath string) {
	err := os.Remove(filePath)
	if err != nil {
		log.Println("删除文件["+filePath+"]失败：", err)
	}
}

// 删除整个目录，无需判断是否存在
func DeleteFolder(dirPath string) {
	err := os.RemoveAll(dirPath)
	if err != nil {
		log.Println("删除目录["+dirPath+"]失败：", err)
	}
}

// 将图像裁剪为正方形（按短边）
func cropToSquare(img image.Image) image.Image {
	bounds := img.Bounds()
	width := bounds.Dx()
	height := bounds.Dy()

	var newImg image.Image

	if width > height {
		// 横向长方形，裁剪左右两端
		x0 := (width - height) / 2
		x1 := x0 + height
		newImg = img.(interface {
			SubImage(r image.Rectangle) image.Image
		}).SubImage(image.Rect(x0, 0, x1, height))
	} else if height > width {
		// 纵向长方形，裁剪上下两端
		y0 := (height - width) / 2
		y1 := y0 + width
		newImg = img.(interface {
			SubImage(r image.Rectangle) image.Image
		}).SubImage(image.Rect(0, y0, width, y1))
	} else {
		// 已经是正方形
		newImg = img
	}

	return newImg
}
